import React, {memo, useEffect, useState} from 'react';

import "./index.css";
import Title from "../../../../../components/Title/Title";
import {Dropdown, Menu, message, Switch, Tabs} from "antd";
import {MENU_STYLE} from "../../../plate/config";
import {useDispatch, useSelector} from "react-redux";
import {
  saveBiologicalCqData,
  saveChartOption,
  saveExperimentSetting,
  saveGeneExpressionTableList,
  saveGeneSetting,
  saveTableData,
  saveTargetCqData,
  saveTechnicalTableData
} from "./store/actionCreators";
import GeneChart from "../../../../../components/chart/GeneChart";
import {deepClone} from "../../../../../common/utils";
import {saveEndogenousControlTarget, saveReferenceGroup, saveReferenceSample} from "../../../plate/store/actionCreators";
import {RELATIVE_LIST, TECHNICAL_REPLICATES_LIST, translateGene} from "./config";
import {WELL_TYPE} from "../../../store/constants";

//  相对定量算法,巨坑,深坑,深渊巨坑,极其混乱,如有修改,建议与他们讨论好具体计算过程,重新写吧
//  确实混乱,头大！
export default memo(function GeneExpression() {
    const {TabPane} = Tabs;
    const dispatch = useDispatch();
    const {
      data,
      geneSetting,
      experimentSetting,
      reduxGroup,
      endogenousControlTarget,
      referenceSample,
      referenceGroup,
      experimentInfo,
      geneExpressionTableList,
      chartOption,
      targetCqData,
      biologicalCqData,
      tableData,
      isCN
    } = useSelector(
      state => ({
        data: state.dataReducer.data,
        geneSetting: state.geneSettingReducer.geneSetting,
        experimentSetting: state.geneSettingReducer.experimentSetting,
        reduxGroup: state.plateReducer.reduxGroup,
        endogenousControlTarget: state.plateReducer.endogenousControlTarget,  // 单内参基因
        referenceSample: state.plateReducer.referenceSample,  // 对照样本
        referenceGroup: state.plateReducer.referenceGroup,  // 对照生物样本
        experimentInfo: state.experimentReducer.experimentInfo,
        geneExpressionTableList: state.geneSettingReducer.geneExpressionTableList,
        chartOption: state.geneSettingReducer.chartOption,  //  barChart设置项
        targetCqData: state.geneSettingReducer.targetCqData, //  存储每个target的cqMean/cqSd的数据结构
        biologicalCqData: state.geneSettingReducer.biologicalCqData, //  存储每个group下的的cqMean/cqSd的数据结构
        tableData: state.geneSettingReducer.tableData, //  表格数据
        isCN: state.languageReducer.isCN
      }));
    const [showInTable, setShowInTable] = useState(false);
    const [technicalReplicatesTitle, setTechnicalReplicatesTitle] = useState([]);

    const [mode, setModel] = useState(["Normalized Expression (ΔΔCq)", "Normalized Expression (Multiple Controls)", "Relative Standard Curve"]);
    const [plotType, setPlotType] = useState(["RQ vs Sample", "RQ vs Target"]);
    const experimentIdentifyTitle = ["Quantitation/Standard Curve", "Quantitation/Relative Standard Curve", "Quantitation/Comparative Cq (△△Cq)", "Melt Curve", "Genotyping", "Presence/Absence"];
    const graphType = ["Linear", "Log10"];
    const orientation = ["Vertical Bars", "Horizontal Bars"];
    let cloneExperimentSetting = {};
    let cloneEndogenousControlTarget = [];
    let cloneTechnicalReplicatesList = [];
    let cloneTableData = [];
    let cloneChartOption = {};

    // 获取 chartObj
    const getChartObj = function (data) {
      let chartObj = {
        rq_sample: {},
        rq_target: {}
      };
      // 获取每个sample对应的target
      data.plateSetting.samples.forEach(item => chartObj.rq_sample[item.name] = []);
      data.wells.forEach(item => {
        if (item.sampleName) {
          item.targets.forEach(it => {
            chartObj.rq_sample[item.sampleName].push(it.name);
          });
        }
      });
      //  去重
      for (const key in chartObj.rq_sample) {
        chartObj.rq_sample[key] = [...new Set(chartObj.rq_sample[key])];
      }
      // 获取每个target对应的sample
      data.plateSetting.targets.forEach(item => chartObj.rq_target[item.name] = []);
      data.wells.forEach(item => {
        if (item.targets.length > 0) {
          item.targets.forEach(it => {
            chartObj.rq_target[it.name].push(item.sampleName);
          });
        }
      });
      //  去重
      for (const key in chartObj.rq_target) {
        chartObj.rq_target[key] = [...new Set(chartObj.rq_target[key])];
      }
      return chartObj;
    };

    const getChartObjGroup = function (data) {
      let chartObj = {
        rq_group: {},
        rq_target: {}
      };
      // 获取每个group对应的target
      experimentSetting.groups?.forEach(item => chartObj.rq_group[item.name] = []);
      data.wells.forEach(item => {
        if (item.groupName) {
          item.targets.forEach(it => {
            chartObj.rq_group[item.groupName].push(it.name);
          });
        }
      });
      //  去重
      for (const key in chartObj.rq_group) {
        chartObj.rq_group[key] = [...new Set(chartObj.rq_group[key])];
      }
      // 获取每个target对应的group
      data.plateSetting.targets.forEach(item => chartObj.rq_target[item.name] = []);
      data.wells.forEach(item => {
        if (item.targets.length > 0) {
          item.targets.forEach(it => {
            chartObj.rq_target[it.name].push(item.groupName);
          });
        }
      });
      //  去重
      for (const key in chartObj.rq_target) {
        chartObj.rq_target[key] = [...new Set(chartObj.rq_target[key])];
      }
      return chartObj;
    };

    // 获取技术重复柱状图数据
    const getAllData = function (chartObj, calcData, experimentSetting) {
      let allData = {};
      let barData = {
        rq_sample: {},
        rq_target: {}
      };
      let posData = {
        rq_sample: {},
        rq_target: {}
      };
      let negData = {
        rq_sample: {},
        rq_target: {}
      };
      let showSamples = experimentSetting.samples.filter(item => item.showChart).map(it => it.name);
      let showTargets = experimentSetting.targets.filter(item => item.showChart).map(it => it.name);
      Object.keys(chartObj.rq_sample).forEach(sampleName => {
        if (!calcData.some(item => item.sample === sampleName) || !showSamples.find(it => it === sampleName)) {
          return;
        }
        let rqData = {},
          positiveData = {},
          negativeData = {};
        calcData.forEach(item => {
          if (item.sample !== sampleName) {
            return;
          }
          rqData[item.target] = item.rq;
          positiveData[item.target] = item.positive;
          negativeData[item.target] = item.negative;
        });
        barData.rq_sample[sampleName] = rqData;
        posData.rq_sample[sampleName] = positiveData;
        negData.rq_sample[sampleName] = negativeData;
      });
      Object.keys(chartObj.rq_target).forEach(targetName => {
        if (!showTargets.find(it => it === targetName)) { //  shouChart联动
          return;
        }
        let rqData = {},
          positiveData = {},
          negativeData = {};
        calcData.forEach(item => {
          if (item.target !== targetName) {
            return;
          }
          rqData[item.sample] = item.rq;
          positiveData[item.sample] = item.positive;
          negativeData[item.sample] = item.negative;
        });
        barData.rq_target[targetName] = rqData;
        posData.rq_target[targetName] = positiveData;
        negData.rq_target[targetName] = negativeData;
      });
      allData["barData"] = barData;
      allData["posData"] = posData;
      allData["negData"] = negData;
      return allData;
    };

    // 获取生物重复柱状图数据
    const getAllGroupData = function (chartObj, calcData, experimentSetting) {
      console.log(chartObj, calcData, experimentSetting);
      let allData = {};
      let barData = {
        rq_group: {},
        rq_target: {}
      };
      let posData = {
        rq_group: {},
        rq_target: {}
      };
      let negData = {
        rq_group: {},
        rq_target: {}
      };
      let showGroups = experimentSetting.groups?.filter(item => item.showChart).map(it => it.name);
      let showTargets = experimentSetting.targets.filter(item => item.showChart).map(it => it.name);
      Object.keys(chartObj.rq_group).forEach(groupName => {
        if (!calcData.some(item => item.group === groupName) || !showGroups.find(it => it === groupName)) {
          return;
        }
        let rqData = {},
          positiveData = {},
          negativeData = {};
        calcData.forEach(item => {
          if (item.group !== groupName) {
            return;
          }
          rqData[item.target] = item.rq;
          positiveData[item.target] = item.positive;
          negativeData[item.target] = item.negative;
        });
        barData.rq_group[groupName] = rqData;
        posData.rq_group[groupName] = positiveData;
        negData.rq_group[groupName] = negativeData;
      });
      Object.keys(chartObj.rq_target).forEach(targetName => {
        if (!showTargets.find(it => it === targetName)) { //  shouChart联动
          return;
        }
        let rqData = {},
          positiveData = {},
          negativeData = {};
        calcData.forEach(item => {
          if (item.target !== targetName) {
            return;
          }
          rqData[item.group] = item.rq;
          positiveData[item.group] = item.positive;
          negativeData[item.group] = item.negative;
        });
        barData.rq_target[targetName] = rqData;
        posData.rq_target[targetName] = positiveData;
        negData.rq_target[targetName] = negativeData;
      });
      allData["barData"] = barData;
      allData["posData"] = posData;
      allData["negData"] = negData;
      return allData;
    };

    // 获取 chart 配置项
    const getChartOption = function (allData) {
      console.log(11111111111);
      let barData = allData.barData,
        posData = allData.posData,
        negData = allData.negData;
      let grid = {
          x: 50,//左
          y: 30, //上
          x2: 30,//右
          y2: 30 //下
        },
        xAxis,
        yAxis,
        series = [],
        option,
        axisTitle;  //  枚举title
      try {
        if (geneSetting.plotType === "RQ vs Sample") {
          axisTitle = Object.keys(barData.rq_sample);
          let aveCount = Object.keys(barData.rq_target).length + 1; //  每个类目中柱状图宽度的等分
          Object.keys(barData.rq_target).forEach((target, indey) => { //  添加柱状图的series
            let seriesItem = {};
            let arrData = [];
            Object.keys(barData.rq_target[target]).forEach((item) => {
              let index = axisTitle.findIndex(it => it === item);
              arrData[index] = barData.rq_target[target][item];
            });
            seriesItem = {
              name: target,
              type: "bar",
              color: data.plateSetting.targets.find(item => item.name === target).color,
              data: arrData,
              barGap: '0',
              barWidth: `${(1 / aveCount) * 100}%`
            };
            series.push(seriesItem);
          });
          Object.keys(barData.rq_target).forEach((target, index) => { //  添加工字图series
            let selfItem = {};
            let errorData = [];
            Object.keys(barData.rq_target[target]).forEach((item) => {
              let index = axisTitle.findIndex(it => it === item),
                barItem = barData.rq_target[target][item],
                posItem = posData.rq_target[target][item] < 0 ? 0 : posData.rq_target[target][item],
                negItem = negData.rq_target[target][item] < 0 ? 0 : negData.rq_target[target][item];
              errorData[index] = [index, barItem - negItem, barItem + posItem];
            });
            // console.log('errorData',errorData);
            //  NaN兜底
            //TODO:加上会导致误差线消失，逻辑再修改
            // for (let i = 0; i < errorData.length; i++) {
            //   if (isNaN(errorData[i])) {
            //     errorData[i] = 0;
            //   }
            // }
            if (geneSetting.orientation === "Vertical Bars") {
              selfItem = {
                type: 'custom',
                name: 'error',
                itemStyle: {
                  borderWidth: 1
                },
                renderItem: function (_, api) {
                  let xValue = api.value(0);  //  errorData[i][0]的值
                  let highPoint = api.coord([xValue, api.value(1)]);  //  errorData[i][1]的像素值,y轴类目的中心的坐标,但是需要加上整个坐标轴的偏移量,这里面手动设置了偏移量30
                  let lowPoint = api.coord([xValue, api.value(2)]); //  errorData[i][2]的像素值,
                  // console.log('xValue', xValue);
                  // console.log('highPoint', highPoint);
                  // console.log('lowPoint', lowPoint);
                  let xHalfWidth = api.size([1, 0])[0];  //  x轴类目的长度
                  let base = xHalfWidth / (aveCount * 2);  //  一个柱状图有2个base组成
                  let hBase = xHalfWidth * 0.1 / aveCount;
                  let x1 = grid.x + 2 * (index + 1) * base + xValue * xHalfWidth;
                  let style = api.style({
                    stroke: "#000",
                    fill: undefined
                  });
                  return {
                    type: 'group',
                    children: [
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1 - hBase,
                          y1: highPoint[1],
                          x2: x1 + hBase,
                          y2: highPoint[1]
                        },
                        style: style
                      },//top
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1,
                          y1: highPoint[1],
                          x2: x1,
                          y2: lowPoint[1]
                        },//mid
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1 - hBase,
                          y1: lowPoint[1],
                          x2: x1 + hBase,
                          y2: lowPoint[1]
                        },
                        style: style
                      }//bottom
                    ]
                  };
                },
                encode: {
                  x: 0, // 表示维度 0 映射到 x 轴。
                  y: [1, 2] // 表示维度 1、2 映射到 y 轴。
                },
                data: errorData,
                z: 100
              };
            } else {
              for (let i = 0; i < errorData.length; i++) {  //  工字型在使用Horizontal时顺序不一样，这里将errorData[i][0]的顺序颠倒
                errorData[i][0] = errorData.length - 1 - i;
              }
              selfItem = {
                type: 'custom',
                name: 'error',
                itemStyle: {
                  borderWidth: 1
                },
                renderItem: function (params, api) {
                  let xValue = api.value(0);  //  errorData[i][0]的值
                  let highPoint = api.coord([api.value(2), xValue]);  //  errorData[i][1]的像素值,x轴类目的中心的坐标,但是需要加上整个坐标轴的偏移量,这里面手动设置了偏移量50
                  let lowPoint = api.coord([api.value(1), xValue]); //  errorData[i][2]的像素值,
                  let yHalfWidth = api.size([1, 0])[1];  //  y轴类目的长度
                  let base = yHalfWidth / (aveCount * 2);  //  一个柱状图有2个base组成
                  let hBase = yHalfWidth * 0.1 / aveCount;
                  let y1 = grid.y + 2 * (index + 1) * base + xValue * yHalfWidth;
                  let style = api.style({
                    stroke: "#000",
                    fill: undefined
                  });
                  return {
                    type: 'group',
                    children: [
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: highPoint[0],
                          y1: y1 - hBase,
                          x2: highPoint[0],
                          y2: y1 + hBase
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: highPoint[0],   //  距离左侧的位置
                          y1: y1,  //  距离上方的位置
                          x2: lowPoint[0],  //  距离左侧的位置
                          y2: y1   //  距离上方的位置
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: lowPoint[0],
                          y1: y1 - hBase,
                          x2: lowPoint[0],
                          y2: y1 + hBase
                        },
                        style: style
                      }
                    ]
                  };
                },
                encode: {
                  x: 0,
                  y: [1, 2]
                },
                data: errorData,
                z: 100
              };
            }
            series.push(selfItem);
          });
        } else {
          axisTitle = Object.keys(barData.rq_target);
          let aveCount = Object.keys(barData.rq_sample).length + 1; //  每个类目中柱状图宽度的等分
          Object.keys(barData.rq_sample).forEach(sample => {
            let seriesItem = {};
            let arrData = [];
            Object.keys(barData.rq_sample[sample]).forEach(item => {
              let index = axisTitle.findIndex(it => it === item);
              arrData[index] = barData.rq_sample[sample][item];
            });
            seriesItem = {
              name: sample,
              stack: sample,
              type: "bar",
              color: data.plateSetting.samples.find(item => item.name === sample).color,
              data: arrData,
              barGap: '0',
              barWidth: `${(1 / aveCount) * 100}%`
            };
            series.push(seriesItem);
          });
          Object.keys(barData.rq_sample).forEach((sample, index) => {
            let selfItem = {};
            let errorData = [];
            Object.keys(barData.rq_sample[sample]).forEach(item => {
              let index = axisTitle.findIndex(it => it === item),
                barItem = barData.rq_sample[sample][item],
                posItem = posData.rq_sample[sample][item] < 0 ? 0 : posData.rq_sample[sample][item],
                negItem = negData.rq_sample[sample][item] < 0 ? 0 : negData.rq_sample[sample][item];
              errorData[index] = [index, barItem - negItem, barItem + posItem];
            });
            //  TODO:NaN兜底会导致误差线丢失，兜底逻辑待修复
            // for (let i = 0; i < errorData.length; i++) {
            //   for (let j = 0; j < errorData[i]?.length; j++) {
            //     console.log(errorData[i][j]);
            //     if (isNaN(errorData[i][j])) {
            //       errorData[i] = 0;
            //     }
            //   }
            //  }
            if (geneSetting.orientation === "Vertical Bars") {
              selfItem = {
                type: 'custom',
                name: 'error',
                itemStyle: {
                  borderWidth: 1
                },
                renderItem: function (params, api) {
                  let xValue = api.value(0);  //  errorData[i][0]的值
                  let highPoint = api.coord([xValue, api.value(1)]);  //  errorData[i][1]的像素值,y轴类目的中心的坐标,但是需要加上整个坐标轴的偏移量,这里面手动设置了偏移量30
                  //TODO:lowPoint为NAN时误差线消失,当xValue不为undefined时对应的为errorData[xValue][2]的值
                  let value2 = api.value(2);
                  if (isNaN(value2) && xValue !== undefined) {
                    value2 = errorData[xValue][2];
                    // debugger
                    // console.log(errorData[xValue]);
                    // console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                  }
                  let lowPoint = api.coord([xValue, value2]); //  errorData[i][2]的像素值,

                  let xHalfWidth = api.size([1, 0])[0];  //  x轴类目的长度
                  let base = xHalfWidth / (aveCount * 2);  //  一个柱状图有2个base组成
                  let hBase = xHalfWidth * 0.1 / aveCount;
                  let x1 = grid.x + 2 * (index + 1) * base + xValue * xHalfWidth;
                  // console.log(sample);
                  // console.log("xValue", xValue, "value1", api.value(1), "value2", value2, "api.value(2)", api.value(2));
                  // console.log(errorData);
                  // console.log("x1", x1);
                  // console.log("hBase", hBase);
                  // console.log("highPoint", highPoint);
                  // console.log("lowPoint", lowPoint);
                  // console.log("===================================================");
                  let style = api.style({
                    stroke: "#000",
                    fill: undefined
                  });
                  return {
                    type: 'group',
                    children: [
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1 - hBase,
                          y1: highPoint[1],   //下横线
                          x2: x1 + hBase,
                          y2: highPoint[1]
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1,
                          y1: highPoint[1],  //中间垂直线
                          x2: x1,
                          y2: lowPoint[1]
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1 - hBase, //上水平线
                          y1: lowPoint[1],
                          x2: x1 + hBase,
                          y2: lowPoint[1]
                        },
                        style: style
                      }
                    ]
                  };
                },
                encode: {
                  x: 0,
                  y: [1, 2]
                },
                data: errorData,
                z: 100
              };
            } else {
              for (let i = 0; i < errorData.length; i++) {  //  工字型在使用Horizontal时顺序不一样，这里将errorData[i][0]的顺序颠倒
                errorData[i][0] = errorData.length - 1 - i;
              }
              selfItem = {
                type: 'custom',
                name: 'error',
                itemStyle: {
                  borderWidth: 1
                },
                renderItem: function (params, api) {
                  let xValue = api.value(0);  //  errorData[i][0]的值
                  let highPoint = api.coord([api.value(1), xValue]);  //  errorData[i][1]的像素值,x轴类目的中心的坐标,但是需要加上整个坐标轴的偏移量,这里面手动设置了偏移量50
                  let lowPoint = api.coord([api.value(2), xValue]); //  errorData[i][2]的像素值,
                  let yHalfWidth = api.size([1, 0])[1];  //  y轴类目的长度
                  let base = yHalfWidth / (aveCount * 2);  //  一个柱状图有2个base组成
                  let hBase = yHalfWidth * 0.1 / aveCount;
                  let y1 = grid.y + 2 * (index + 1) * base + xValue * yHalfWidth;
                  let style = api.style({
                    stroke: "#000",
                    fill: undefined
                  });
                  return {
                    type: 'group',
                    children: [
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: highPoint[0],
                          y1: y1 - hBase,
                          x2: highPoint[0],
                          y2: y1 + hBase
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: highPoint[0],   //  距离左侧的位置
                          y1: y1,  //  距离上方的位置
                          x2: lowPoint[0],  //  距离左侧的位置
                          y2: y1   //  距离上方的位置
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: lowPoint[0],
                          y1: y1 - hBase,
                          x2: lowPoint[0],
                          y2: y1 + hBase
                        },
                        style: style
                      }
                    ]
                  };
                },
                encode: {
                  x: 0,
                  y: [1, 2]
                },
                data: errorData,
                z: 100
              };
            }
            series.push(selfItem);
          });
        }
      } catch (e) {
        console.log(e);
      }
      //  位置配置
      //  orientation选项
      console.log(axisTitle);
      if (geneSetting.orientation === "Vertical Bars") {
        xAxis = {
          type: "category",
          data: axisTitle,
          axisLabel: axisTitle.length > 15 ? {
            interval: 0,
            fontSize: 10,
            rotate: 90,
            margin: 2,
            inside: false
          } : {}
        };
        yAxis = {
          type: "value",
        };
      } else {
        xAxis = {
          type: "value",
          boundaryGap: [0, "5%"]

        };
        yAxis = {
          type: "category",
          data: axisTitle,
          axisLabel: axisTitle.length > 15 ? {
            fontSize: 10,
            margin: 2
          } : {}
          // axisLabel: { //坐标轴刻度标签的相关设置。
          //   formatter: function (params) {
          //     let newParamsName = params; // 最终拼接成的字符串
          //     let paramsNameNumber = params.length; // 实际标签的个数
          //     let provideNumber = 3; // 每行能显示的字的个数
          //     if (paramsNameNumber > provideNumber) {
          //       newParamsName = params.substring(0, provideNumber) + "\n" + "...";
          //     }
          //     //将最终的字符串返回
          //     return newParamsName;
          //   }
          // }
        };
      }
      option = {
        grid,
        xAxis,
        yAxis,
        series,
        animation: false, //  取消动画效果
        silent: true  //  取消鼠标悬浮高亮效果
      };
      console.log(option);
      return option;
    };


    // 获取 chart 配置项
    const getChartGroupOption = function (allData) {
      let barData = allData.barData,
        posData = allData.posData,
        negData = allData.negData;
      let grid = {
          x: 50,//左
          y: 30, //上
          x2: 30,//右
          y2: 30 //下
        },
        xAxis,
        yAxis,
        series = [],
        option,
        axisTitle;  //  枚举title
      try {
        if (geneSetting.plotType === "RQ vs BioGroup") {
          axisTitle = Object.keys(barData.rq_group);
          let aveCount = Object.keys(barData.rq_target).length + 1; //  每个类目中柱状图宽度的等分
          Object.keys(barData.rq_target).forEach((target, indey) => { //  添加柱状图的series
            let seriesItem = {};
            let arrData = [];
            Object.keys(barData.rq_target[target]).forEach((item) => {
              let index = axisTitle.findIndex(it => it === item);
              arrData[index] = barData.rq_target[target][item];
            });
            seriesItem = {
              name: target,
              type: "bar",
              color: data.plateSetting.targets.find(item => item.name === target).color,
              data: arrData,
              barGap: '0',
              barWidth: `${(1 / aveCount) * 100}%`
            };
            series.push(seriesItem);
          });
          Object.keys(barData.rq_target).forEach((target, index) => { //  添加工字图series
            let selfItem = {};
            let errorData = [];
            Object.keys(barData.rq_target[target]).forEach((item) => {
              let index = axisTitle.findIndex(it => it === item),
                barItem = barData.rq_target[target][item],
                posItem = posData.rq_target[target][item] < 0 ? 0 : posData.rq_target[target][item],
                negItem = negData.rq_target[target][item] < 0 ? 0 : negData.rq_target[target][item];
              errorData[index] = [index, barItem - negItem, barItem + posItem];
            });
            // console.log('errorData',errorData);
            //  NaN兜底
            //TODO:加上会导致误差线消失，逻辑再修改
            // for (let i = 0; i < errorData.length; i++) {
            //   if (isNaN(errorData[i])) {
            //     errorData[i] = 0;
            //   }
            // }
            if (geneSetting.orientation === "Vertical Bars") {
              selfItem = {
                type: 'custom',
                name: 'error',
                itemStyle: {
                  borderWidth: 1
                },
                renderItem: function (_, api) {
                  let xValue = api.value(0);  //  errorData[i][0]的值
                  let highPoint = api.coord([xValue, api.value(1)]);  //  errorData[i][1]的像素值,y轴类目的中心的坐标,但是需要加上整个坐标轴的偏移量,这里面手动设置了偏移量30
                  let lowPoint = api.coord([xValue, api.value(2)]); //  errorData[i][2]的像素值,
                  // console.log('xValue', xValue);
                  // console.log('highPoint', highPoint);
                  // console.log('lowPoint', lowPoint);
                  let xHalfWidth = api.size([1, 0])[0];  //  x轴类目的长度
                  let base = xHalfWidth / (aveCount * 2);  //  一个柱状图有2个base组成
                  let hBase = xHalfWidth * 0.1 / aveCount;
                  let x1 = grid.x + 2 * (index + 1) * base + xValue * xHalfWidth;
                  let style = api.style({
                    stroke: "#000",
                    fill: undefined
                  });
                  return {
                    type: 'group',
                    children: [
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1 - hBase,
                          y1: highPoint[1],
                          x2: x1 + hBase,
                          y2: highPoint[1]
                        },
                        style: style
                      },//top
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1,
                          y1: highPoint[1],
                          x2: x1,
                          y2: lowPoint[1]
                        },//mid
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1 - hBase,
                          y1: lowPoint[1],
                          x2: x1 + hBase,
                          y2: lowPoint[1]
                        },
                        style: style
                      }//bottom
                    ]
                  };
                },
                encode: {
                  x: 0, // 表示维度 0 映射到 x 轴。
                  y: [1, 2] // 表示维度 1、2 映射到 y 轴。
                },
                data: errorData,
                z: 100
              };
            } else {
              for (let i = 0; i < errorData.length; i++) {  //  工字型在使用Horizontal时顺序不一样，这里将errorData[i][0]的顺序颠倒
                errorData[i][0] = errorData.length - 1 - i;
              }
              selfItem = {
                type: 'custom',
                name: 'error',
                itemStyle: {
                  borderWidth: 1
                },
                renderItem: function (params, api) {
                  let xValue = api.value(0);  //  errorData[i][0]的值
                  let highPoint = api.coord([api.value(2), xValue]);  //  errorData[i][1]的像素值,x轴类目的中心的坐标,但是需要加上整个坐标轴的偏移量,这里面手动设置了偏移量50
                  let lowPoint = api.coord([api.value(1), xValue]); //  errorData[i][2]的像素值,
                  let yHalfWidth = api.size([1, 0])[1];  //  y轴类目的长度
                  let base = yHalfWidth / (aveCount * 2);  //  一个柱状图有2个base组成
                  let hBase = yHalfWidth * 0.1 / aveCount;
                  let y1 = grid.y + 2 * (index + 1) * base + xValue * yHalfWidth;
                  let style = api.style({
                    stroke: "#000",
                    fill: undefined
                  });
                  return {
                    type: 'group',
                    children: [
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: highPoint[0],
                          y1: y1 - hBase,
                          x2: highPoint[0],
                          y2: y1 + hBase
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: highPoint[0],   //  距离左侧的位置
                          y1: y1,  //  距离上方的位置
                          x2: lowPoint[0],  //  距离左侧的位置
                          y2: y1   //  距离上方的位置
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: lowPoint[0],
                          y1: y1 - hBase,
                          x2: lowPoint[0],
                          y2: y1 + hBase
                        },
                        style: style
                      }
                    ]
                  };
                },
                encode: {
                  x: 0,
                  y: [1, 2]
                },
                data: errorData,
                z: 100
              };
            }
            series.push(selfItem);
          });
        } else {
          axisTitle = Object.keys(barData.rq_target);
          let aveCount = Object.keys(barData.rq_group).length + 1; //  每个类目中柱状图宽度的等分
          Object.keys(barData.rq_group).forEach(group => {
            let seriesItem = {};
            let arrData = [];
            Object.keys(barData.rq_group[group]).forEach(item => {
              let index = axisTitle.findIndex(it => it === item);
              arrData[index] = barData.rq_group[group][item];
            });
            seriesItem = {
              name: group,
              stack: group,
              type: "bar",
              color: experimentSetting.groups?.find(item => item.name === group).color,
              data: arrData,
              barGap: '0',
              barWidth: `${(1 / aveCount) * 100}%`
            };
            series.push(seriesItem);
          });
          Object.keys(barData.rq_group).forEach((group, index) => {
            let selfItem = {};
            let errorData = [];
            Object.keys(barData.rq_group[group]).forEach(item => {
              let index = axisTitle.findIndex(it => it === item),
                barItem = barData.rq_group[group][item],
                posItem = posData.rq_group[group][item] < 0 ? 0 : posData.rq_group[group][item],
                negItem = negData.rq_group[group][item] < 0 ? 0 : negData.rq_group[group][item];
              errorData[index] = [index, barItem - negItem, barItem + posItem];
            });
            //  TODO:NaN兜底会导致误差线丢失，兜底逻辑待修复
            // for (let i = 0; i < errorData.length; i++) {
            //   for (let j = 0; j < errorData[i]?.length; j++) {
            //     console.log(errorData[i][j]);
            //     if (isNaN(errorData[i][j])) {
            //       errorData[i] = 0;
            //     }
            //   }
            //  }
            if (geneSetting.orientation === "Vertical Bars") {
              selfItem = {
                type: 'custom',
                name: 'error',
                itemStyle: {
                  borderWidth: 1
                },
                renderItem: function (params, api) {
                  let xValue = api.value(0);  //  errorData[i][0]的值
                  let highPoint = api.coord([xValue, api.value(1)]);  //  errorData[i][1]的像素值,y轴类目的中心的坐标,但是需要加上整个坐标轴的偏移量,这里面手动设置了偏移量30
                  //TODO:lowPoint为NAN时误差线消失,当xValue不为undefined时对应的为errorData[xValue][2]的值
                  let value2 = api.value(2);
                  if (isNaN(value2) && xValue !== undefined) {
                    value2 = errorData[xValue][2];
                    // console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                  }
                  let lowPoint = api.coord([xValue, value2]); //  errorData[i][2]的像素值,

                  let xHalfWidth = api.size([1, 0])[0];  //  x轴类目的长度
                  let base = xHalfWidth / (aveCount * 2);  //  一个柱状图有2个base组成
                  let hBase = xHalfWidth * 0.1 / aveCount;
                  let x1 = grid.x + 2 * (index + 1) * base + xValue * xHalfWidth;
                  let style = api.style({
                    stroke: "#000",
                    fill: undefined
                  });
                  return {
                    type: 'group',
                    children: [
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1 - hBase,
                          y1: highPoint[1],   //下横线
                          x2: x1 + hBase,
                          y2: highPoint[1]
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1,
                          y1: highPoint[1],  //中间垂直线
                          x2: x1,
                          y2: lowPoint[1]
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: x1 - hBase, //上水平线
                          y1: lowPoint[1],
                          x2: x1 + hBase,
                          y2: lowPoint[1]
                        },
                        style: style
                      }
                    ]
                  };
                },
                encode: {
                  x: 0,
                  y: [1, 2]
                },
                data: errorData,
                z: 100
              };
            } else {
              for (let i = 0; i < errorData.length; i++) {  //  工字型在使用Horizontal时顺序不一样，这里将errorData[i][0]的顺序颠倒
                errorData[i][0] = errorData.length - 1 - i;
              }
              selfItem = {
                type: 'custom',
                name: 'error',
                itemStyle: {
                  borderWidth: 1
                },
                renderItem: function (params, api) {
                  let xValue = api.value(0);  //  errorData[i][0]的值
                  let highPoint = api.coord([api.value(1), xValue]);  //  errorData[i][1]的像素值,x轴类目的中心的坐标,但是需要加上整个坐标轴的偏移量,这里面手动设置了偏移量50
                  let lowPoint = api.coord([api.value(2), xValue]); //  errorData[i][2]的像素值,
                  let yHalfWidth = api.size([1, 0])[1];  //  y轴类目的长度
                  let base = yHalfWidth / (aveCount * 2);  //  一个柱状图有2个base组成
                  let hBase = yHalfWidth * 0.1 / aveCount;
                  let y1 = grid.y + 2 * (index + 1) * base + xValue * yHalfWidth;
                  let style = api.style({
                    stroke: "#000",
                    fill: undefined
                  });
                  return {
                    type: 'group',
                    children: [
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: highPoint[0],
                          y1: y1 - hBase,
                          x2: highPoint[0],
                          y2: y1 + hBase
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: highPoint[0],   //  距离左侧的位置
                          y1: y1,  //  距离上方的位置
                          x2: lowPoint[0],  //  距离左侧的位置
                          y2: y1   //  距离上方的位置
                        },
                        style: style
                      },
                      {
                        type: 'line',
                        transition: ['shape'],
                        shape: {
                          x1: lowPoint[0],
                          y1: y1 - hBase,
                          x2: lowPoint[0],
                          y2: y1 + hBase
                        },
                        style: style
                      }
                    ]
                  };
                },
                encode: {
                  x: 0,
                  y: [1, 2]
                },
                data: errorData,
                z: 100
              };
            }
            series.push(selfItem);
          });
        }
      } catch (e) {
        console.log(e);
      }
      //  位置配置
      //  orientation选项
      if (geneSetting.orientation === "Vertical Bars") {
        xAxis = {
          type: "category",
          data: axisTitle
        };
        yAxis = {
          type: "value"
        };
      } else {
        xAxis = {
          type: "value",
          boundaryGap: [0, "5%"]
        };
        yAxis = {
          type: "category",
          data: axisTitle
          // axisLabel: { //坐标轴刻度标签的相关设置。
          //   formatter: function (params) {
          //     let newParamsName = params; // 最终拼接成的字符串
          //     let paramsNameNumber = params.length; // 实际标签的个数
          //     let provideNumber = 3; // 每行能显示的字的个数
          //     if (paramsNameNumber > provideNumber) {
          //       newParamsName = params.substring(0, provideNumber) + "\n" + "...";
          //     }
          //     //将最终的字符串返回
          //     return newParamsName;
          //   }
          // }
        };
      }
      option = {
        grid,
        xAxis,
        yAxis,
        series,
        animation: false, //  取消动画效果
        silent: true  //  取消鼠标悬浮高亮效果
      };
      return option;
    };

    // 单内参计算
    const getSingleCalc = function (targetCqData, e) {
      targetCqData = targetCqData || {};
      let calcData = [],
        power = e + 1,
        referenceGenes = endogenousControlTarget.find(item => item.opt)?.name; //  内参基因
      if (!referenceGenes || !referenceSample) {  //  没有选内参基因和对照样本,不进行计算
        if (geneSetting.activeIndex === 2 && !referenceSample) {
          message.warn("没有选对照样本");
        }
        return {calcData: [], calcGroupData: []};
      }
      let sampleNames = Object.keys(targetCqData),
        referenceSampleKeys = Object.keys(targetCqData[referenceSample] || {}),
        referenceSample_Cq = {},  //  对照样本中每个 target 的 ΔCq
        referenceSampleGenesCqMean = targetCqData[referenceSample]?.[referenceGenes]?.cqMean;  //  对照样本内参基因的 cqMean
      referenceSampleKeys.forEach(item => referenceSample_Cq[item] = targetCqData[referenceSample]?.[item]?.cqMean - referenceSampleGenesCqMean);
      sampleNames.forEach(sample => {
        let sampleInData = data.plateSetting.samples.find(item => item.name === sample);
        if (sampleInData?.type !== WELL_TYPE.UNK) {
          return;
        }
        let targetNames = Object.keys(targetCqData[sample] || {}), //  每个 sample 中包含的 target
          referenceGenesCqMean = targetCqData[sample]?.[referenceGenes]?.cqMean,  //  内参基因的 cqMean
          referenceGenesCqSd = targetCqData[sample]?.[referenceGenes]?.cqSd;  //  内参基因的 cqSd
        targetNames.forEach(target => {
          //  找到该target的e值
          let power = experimentSetting.targets.find(item => item.name === target).e + 1;
          if (target === referenceGenes) {
            return;
          }
          let newData,
            cqMean = targetCqData[sample]?.[target]?.cqMean,//非内参基因的target的cqMean
            cqSd = targetCqData[sample]?.[target]?.cqSd,//非内参基因的target的cqSd
            _cq, _cqSd, __cq, rq, rqMin, rqMax, positive, negative;
          if (target === referenceGenes) {  //  内参基因
            _cq = _cqSd = __cq = rq = rqMin = rqMax = positive = negative = "-";
          } else {  //  目的基因
            _cq = cqMean - referenceGenesCqMean;//referenceGenesCqMean内参基因的CqMean 当前算的ΔCq
            _cqSd = Math.sqrt(cqSd ** power + referenceGenesCqSd ** power);//平方根 ΔCqSD
            __cq = _cq - referenceSample_Cq[target]; //ΔΔCq
            rq = Math.pow(power, -__cq);
            rqMin = Math.pow(power, -(__cq + _cqSd));
            rqMax = Math.pow(power, -(__cq - _cqSd));
            positive = rq - rqMin;
            negative = rqMax - rq;
          }
          newData = {
            sample,
            target,
            cqMean,
            cqSd,
            _cq,
            _cqSd,
            __cq,
            rq,
            rqMin,
            rqMax,
            positive,
            negative
          };
          calcData.push(newData);
        });
      });
      //TODO:生物重复
      let calcGroupData = [];
      cloneExperimentSetting = deepClone(experimentSetting, cloneExperimentSetting);
      if (cloneExperimentSetting.groups?.some(it => it.reference === true)) {
        let biological = {};
        let biologicalCqData_ = {};
        biologicalCqData_ = deepClone(biologicalCqData, biologicalCqData_);//按照group-sample-target分
        let arr = Object.entries(biologicalCqData_);
        for (let i = 0; i < arr.length; i++) {
          let samples = arr[i][1];
          let groupItem = arr[i][0];
          let samp = {};
          for (let j = 0; j < samples.length; j++) {
            let sample = samples[j];
            let it = targetCqData[sample];
            for (let k = 0; k < Object.entries(it).length; k++) {
              let target = Object.entries(it)[k][0];
              let value = Object.entries(it)[k][1];
              if (samp[target] instanceof Array) {
                samp[target].push(value);
              } else {
                samp[target] = [];
                samp[target].push(value);
              }
            }
          }
          let item;
          for (let j = 0; j < Object.entries(samp).length; j++) {
            let target = Object.entries(samp)[j][0];
            let tarVal = Object.entries(samp)[j][1];
            let cqMean = tarVal.reduce((pre, cur) => pre + cur.cqMean, 0) / tarVal.length;//  Cq平均值
            let cqSd = tarVal.reduce((pre, cur) => pre + cur.cqSd, 0) / tarVal.length;//  CqSd平均值
            item = {
              cqMean,
              cqSd,
              sq: -1,
              sqMean: -1,
              sqSd: -1,
              log2RqMean: null,
              log2RqSd: null
            };
            if (biological[groupItem] instanceof Object) {
              biological[groupItem][target] = item;
            } else {
              biological[groupItem] = {};
              biological[groupItem][target] = item;
            }
          }
        }
        let controlGroupName = cloneExperimentSetting.groups?.find(it => it.reference === true)?.name; //生物对照组
        let referenceControl_Cq = {};  //  对照group样本中每个 target 的 ΔCq

        let controlGroup = biological[controlGroupName];//生物对照组
        let referenceControlGenesCqMean = controlGroup[referenceGenes]?.cqMean;
        Object.keys(biological[controlGroupName]).forEach(item => referenceControl_Cq[item] = controlGroup[item]?.cqMean - referenceControlGenesCqMean);
        let groupNames = Object.keys(biological);
        groupNames.forEach(group => {//每一group组
          let targets = Object.keys(biological[group]);
          let newData = {};
          targets.forEach(target => { //每一group的target组
            //内参的一组的CqMean值
            let biologicalCqDatumElement = biological[group][referenceGenes]; //内参的一组数据
            let referenceGenesCqMean = biologicalCqDatumElement.cqMean;//  内参基因Cq平均值
            let referenceGenesCqSd = biologicalCqDatumElement.cqSd;//  内参基因CqSd平均值
            //  找到该target的e值
            let power = experimentSetting.targets.find(item => item.name === target).e + 1;
            let dataItem = biological[group][target];
            let cqMean = dataItem.cqMean, //非内参基因的target的cqMean
              cqSd = dataItem.cqSd, //非内参基因的target的cqSd
              _cq, _cqSd, __cq, rq, rqMin, rqMax, positive, negative;
            if (target === referenceGenes) {
              return;
            }
            if (target === referenceGenes) {  //  内参基因
              _cq = _cqSd = __cq = rq = rqMin = rqMax = positive = negative = "-";
            } else {  //  目的基因
              _cq = cqMean - referenceGenesCqMean;//referenceGenesCqMean内参基因的CqMean 当前算的ΔCq
              _cqSd = Math.sqrt(cqSd ** power + referenceGenesCqSd ** power);//平方根 ΔCqSD
              __cq = _cq - referenceControl_Cq[target]; //ΔΔCq
              rq = Math.pow(power, -__cq);
              rqMin = Math.pow(power, -(__cq + _cqSd));
              rqMax = Math.pow(power, -(__cq - _cqSd));
              positive = rq - rqMin;
              negative = rqMax - rq;
            }
            newData = {
              group,
              target,
              cqMean,
              cqSd,
              _cq,
              _cqSd,
              __cq,
              rq,
              rqMin,
              rqMax,
              positive,
              negative
            };
            calcGroupData.push(newData);
          });

        });
      }
      return {calcData, calcGroupData};
    };

    // 多内参计算
    const getMultipleCalc = function (targetCqData, e) {
      targetCqData = targetCqData || {};
      let calcData = [],
        power = e + 1,
        referenceGenes = endogenousControlTarget.filter(item => item.opt).map(it => it.name); //  内参基因
      if (referenceGenes.length === 0 || !referenceSample) {  //  没有选内参基因和对照样本,不进行计算
        return calcData;
      }
      let sampleNames = Object.keys(targetCqData);
      sampleNames.forEach(sample => {
        let sampleInData = data.plateSetting.samples.find(item => item.name === sample);
        if (sampleInData?.type !== WELL_TYPE.UNK) {
          return;
        }
        let targetNames = Object.keys(targetCqData[sample] || {}), //  每个 sample 中包含的 target
          _cq2Reference,
          cqSdMean,
          cqSdSum = 0,
          num = 0,
          _cq2Sum = 1;
        referenceGenes.forEach(item => {  //  计算内参基因的 Cq SD Mean 和 2^ΔCq
          cqSdSum += targetCqData[sample][item]?.cqSd;
          num++;
          _cq2Sum *= Math.pow(2, targetCqData[referenceSample][item]?.cqMean - targetCqData[sample]?.[item]?.cqMean);
        });
        _cq2Reference = Math.pow(_cq2Sum, 1 / num); //  内参基因的 2^ΔCq
        cqSdMean = cqSdSum / num; //  Cq SD Mean
        targetNames.forEach(target => {
          //  找到该target的e值
          let power = experimentSetting.targets.find(item => item.name === target).e + 1;
          if (referenceGenes.includes(target)) {
            return;
          }
          let newData,
            cqMean = targetCqData[sample]?.[target]?.cqMean,
            cqSd = targetCqData[sample]?.[target]?.cqSd,
            _cq, _cqSd, _cq2, __cq, rq, rqMin, rqMax, positive, negative;
          _cq = targetCqData[referenceSample][target]?.cqMean - cqMean;
          _cq2 = Math.pow(2, _cq);
          if (referenceGenes.includes(target)) {  //  内参基因
            _cqSd = "-";
            rq = "-";
            __cq = "-";
            rqMin = "-";
            rqMax = "-";
            positive = "-";
            negative = "-";
          } else {  //  非内参基因
            _cqSd = Math.sqrt(cqSd ** power + cqSdMean ** power);
            rq = _cq2 / _cq2Reference;
            __cq = -Math.log2(rq);
            rqMin = Math.pow(2, -(__cq + _cqSd));
            rqMax = Math.pow(2, -(__cq - _cqSd));
            positive = rqMax - rq;
            negative = rq - rqMin;
          }
          newData = {
            sample,
            target,
            cqMean,
            cqSd,
            _cq,
            _cqSd,
            __cq,
            rq,
            rqMin,
            rqMax,
            positive,
            negative
          };
          calcData.push(newData);
        });
      });
      return calcData;
    };

    //  Relative Standard Curve 计算
    const getRelativeCalc = function (targetCqData, e) {
      targetCqData = targetCqData || {};
      let calcData = [],
        power = e + 1,
        referenceGenes = endogenousControlTarget.find(item => item.opt)?.name; //  内参基因
      if (!referenceGenes || !referenceSample) {  //  没有选内参基因和对照样本,不进行计算
        return calcData;
      }
      let referenceSampleGenesSqMean = targetCqData[referenceSample]?.[referenceGenes]?.sqMean;  //  对照样本内参基因的 sqMean
      let sampleNames = Object.keys(targetCqData);
      sampleNames.forEach(sample => {
        let sampleInData = data.plateSetting.samples.find(item => item.name === sample);
        if (sampleInData?.type !== WELL_TYPE.UNK) {
          return;
        }
        let targetNames = Object.keys(targetCqData[sample] || {}), //  每个 sample 中包含的 target
          referenceGenesSqMean = targetCqData[sample]?.[referenceGenes]?.sqMean;  //  内参基因的 sqMean
        targetNames.forEach(target => {
          if (referenceGenes === target) {
            return;
          }
          let newData,
            cqMean = targetCqData[sample]?.[target]?.cqMean,
            sqMean = targetCqData[sample]?.[target]?.sqMean,
            cqSd = targetCqData[sample]?.[target]?.cqSd,
            sqSd = targetCqData[sample]?.[target]?.sqSd,
            _sq,
            rq,
            subtract,
            plus,
            rqMin,
            rqMax,
            positive,
            negative;
          if (referenceGenes === target) {  //  内参基因
            _sq = rq = rqMin = rqMax = positive = negative = "-";
          } else {  //  非内参基因
            let referenceSample_sq = targetCqData[referenceSample]?.[target]?.sqMean / referenceSampleGenesSqMean; //  对照样本中该基因的 _sq
            _sq = targetCqData[sample]?.[target].sqMean / referenceGenesSqMean;
            rq = _sq / referenceSample_sq;
            subtract = targetCqData[sample]?.[target].log2RqMean - targetCqData[sample]?.[target].log2RqSd;
            plus = targetCqData[sample]?.[target].log2RqMean + targetCqData[sample]?.[target].log2RqSd;
            rqMin = Math.pow(power, subtract);
            rqMax = Math.pow(power, plus);
            positive = rq - rqMin;
            negative = rqMax - rq;
          }
          newData = {
            sample,
            target,
            cqMean,
            sqMean,
            cqSd,
            sqSd,
            rq,
            rqMin,
            rqMax,
            positive,
            negative
          };
          calcData.push(newData);
        });
      });
      return calcData;
    };

    //  获取表格数据
    const getTableData = function (calcData, tableType) {
      cloneTableData = deepClone(tableData, cloneTableData);
      try {
        let map = new Map();
        geneExpressionTableList.forEach(item => map.set(item.name, item.selected));
        if (tableType === 1) {
          cloneTableData = calcData.map((item, index) => {
            return {
              tag: {
                value: index + 1,
                show: map.get("#")
              },
              omit: {
                value: cloneTableData[index]?.omit.value || false,
                show: map.get("Omit")
                // show: isCN ? map.get("忽略") : map.get("Omit")
              },
              target: {
                value: item.target,
                show: map.get("Target")
                // show: isCN ? map.get("基因") : map.get("Target")
              },
              biological: {
                value: geneSetting.activeIndex === 2 ? item.group : item.sample,
                show: map.get("Biological") || map.get("Sample")
                // show: isCN ? map.get("Biological") || map.get("样品") : map.get("Biological") || map.get("Sample")
              },
              cqMean: {
                value: item.cqMean,
                // show: isCN ? map.get("Cq平均值") : map.get("Cq Mean")
                show: map.get("Cq Mean")
              },
              _cqMean: {
                value: item._cq,
                show: map.get("ΔCq Mean")
              },
              _cqSd: {
                value: item._cqSd,
                show: map.get("ΔCq SD")
              },
              __cq: {
                value: item.__cq,
                show: map.get("ΔΔCq")
              },
              rq: {
                value: item.rq,
                show: map.get("RQ")
              },
              rqMin: {
                value: item.rqMin,
                show: map.get("RQ Min")
              },
              rqMax: {
                value: item.rqMax,
                show: map.get("RQ Max")
              }
            };
          });
        } else {
          //  TODO:
          //  Map中存放的是表格的title名字
          cloneTableData = calcData.map((item, index) => {
            return {
              tag: {
                value: index + 1,
                show: map.get("#")
              },
              omit: {
                value: cloneTableData[index]?.omit.value || false,
                show: map.get("Omit")
                // show: isCN ? map.get("忽略") : map.get("Omit")
              },
              target: {
                value: item.target,
                show: map.get("Target")
                // show: isCN ? map.get("基因") : map.get("Target")
              },
              biological: {
                value: item.sample,
                show: map.get("Biological") || map.get("Sample")
                // show: isCN ? map.get("Biological") || map.get("样品") : map.get("Biological") || map.get("Sample")
              },
              cqMean: {
                value: item.cqMean,
                show: map.get("Cq Mean")
                // show: isCN ? map.get("Cq 平均值") : map.get("Cq Mean")
              },
              _cqMean: {  //  quantity Mean
                value: item.sqMean,
                show: map.get("ΔCq Mean") || map.get("Quantity Mean")
              },
              _cqSd: {
                value: item.sqSd, //  quantity sd
                show: map.get("ΔCq SD") || map.get("Quantity Sd")
              },
              rq: {
                value: item.rq,
                show: map.get("RQ")
              },
              rqMin: {
                value: item.rqMin,
                show: map.get("RQ Min")
              },
              rqMax: {
                value: item.rqMax,
                show: map.get("RQ Max")
              }
            };
          });
        }
        return cloneTableData;
      } catch (e) {
        console.log(e);
      }
    };

    //  根据 Experiment 界面设置 modeP
    useEffect(() => {
      if (experimentInfo.experimentIdentify === experimentIdentifyTitle[1]) {
        dispatch(saveGeneSetting({...geneSetting, mode: mode[2]}));
      } else if (experimentInfo.experimentIdentify === experimentIdentifyTitle[2]) {
        dispatch(saveGeneSetting({...geneSetting, mode: mode[0]}));
      }
    }, [experimentInfo]);

    //  获取每个 group 分组的sample、获取每个 group 分组的target
    useEffect(() => {
      let biologicalCqData = {};//分组的sample
      let wellList = [];
      //  获取所有含 groupName 的 well 赋值给 biologicalCqData
      data.wells.forEach(item => {
        if (!item.groupName) {
          return;
        }
        wellList.push(item);
        biologicalCqData[item.groupName] = [];
      });
      try {
        //  给 biologicalCqData 赋值每个 groupName 对应的 target 及其对应的 cqMean, cqSd, sq, sqMean, sqSd
        wellList.forEach(item => {
          biologicalCqData[item.groupName].push(item.sampleName);
          biologicalCqData[item.groupName] = [...new Set(biologicalCqData[item.groupName])];
        });
        dispatch(saveBiologicalCqData(biologicalCqData));
      } catch (e) {
        console.log(e);
      }
    }, [data]);

    //  获取每个 target 的 cqMean, cqSd, sq, sqSd, sqMean, log2RqMean
    useEffect(() => {
      let targetCqData = {};
      let wellList = [];
      //  获取所有含 sampleName 的 well 赋值给 targetCqData
      data.wells.forEach(item => {
        if (!item.sampleName) {
          return;
        }
        wellList.push(item);
        targetCqData[item.sampleName] = {};
      });
      let log2Rq = {};
      try {
        //  给 targetCqData 赋值每个 sampleName 对应的 target 及其对应的 cqMean, cqSd, sq, sqMean, sqSd
        wellList.forEach(item => {
          let sampleName = item.sampleName;
          log2Rq[sampleName] = {};
          item.targets.forEach(it => {
            let cqMean = item.lines[it.channelIndex].cqMean,
              cqSd = item.lines[it.channelIndex].cqSd,
              sq = item.lines[it.channelIndex].sq,
              sqMean = item.lines[it.channelIndex].sqMean,
              sqSd = item.lines[it.channelIndex].sqSd;
            // e = it.e < 0 ? 1 : it.e;
            if (cqMean !== -1) {
              targetCqData[sampleName][it.name] = {};
              targetCqData[sampleName][it.name]["cqMean"] = cqMean;
              targetCqData[sampleName][it.name]["cqSd"] = cqSd;
              targetCqData[sampleName][it.name]["sq"] = sq;
              targetCqData[sampleName][it.name]["sqMean"] = sqMean;
              targetCqData[sampleName][it.name]["sqSd"] = sqSd;
              // targetCqData[sampleName][it.name]["e"] = e;
            }
          });
        });
        wellList.forEach(item => {  //  获取每个 well 中的每个 target 的 log2Rq 值
          let sampleName = item.sampleName;
          item.targets.forEach(target => {
            let referenceGenes = endogenousControlTarget.find(item => item.opt)?.name, //  内参基因
              referenceSampleGenesSqMean = targetCqData[referenceSample]?.[referenceGenes]?.sqMean,  //  对照样本内参基因的 sqMean
              referenceSample_sq = targetCqData[referenceSample]?.[target.name]?.sqMean / referenceSampleGenesSqMean, //  对照样本中该基因的 _sq
              referenceGenesSqMean = targetCqData[sampleName]?.[referenceGenes]?.sqMean;  //  内参基因的 sqMean
            let sq = item.lines[target.channelIndex].sq;
            if (log2Rq[sampleName][target.name]) {
              log2Rq[sampleName][target.name].push(Math.log2((sq / referenceGenesSqMean) / referenceSample_sq));
            } else {
              log2Rq[sampleName][target.name] = [Math.log2((sq / referenceGenesSqMean) / referenceSample_sq)];
            }
          });
        });
        let sampleNames = Object.keys(log2Rq);
        sampleNames.forEach(sample => { //  计算每个 target 的 log2RqMean 值
          let targetNames = Object.keys(log2Rq[sample]);
          targetNames.forEach(target => {
            let sum = log2Rq[sample][target].reduce((total, cur) => {
              return total + cur;
            }, 0);
            let log2RqMean = sum / log2Rq[sample][target].length,
              deviations = log2Rq[sample][target].map(x => x - log2RqMean),
              log2RqSd = Math.sqrt(deviations.map(x => x * x).reduce((total, cur) => {
                return total + cur;
              }, 0) / (log2Rq[sample][target].length));
            if (targetCqData[sample]?.[target]) {
              targetCqData[sample][target]["log2RqMean"] = log2RqMean;
              targetCqData[sample][target]["log2RqSd"] = log2RqSd;
            }
          });
        });
        // console.log('targetCqData', targetCqData);
        dispatch(saveTargetCqData(targetCqData));
      } catch (e) {
        console.log(e);
      }
    }, [data, geneSetting, experimentSetting, endogenousControlTarget, referenceSample]);

    // 设置 table 的 title
    useEffect(() => {
      let tableList, title;
      if (experimentInfo.experimentIdentify === experimentIdentifyTitle[1]) {
        tableList = RELATIVE_LIST;
      } else {
        tableList = TECHNICAL_REPLICATES_LIST;
      }
      title = tableList.filter(item => item.selected);
      dispatch(saveGeneExpressionTableList(tableList));
      setTechnicalReplicatesTitle(title);
    }, []);

    //  更新表格和柱状图
    useEffect(() => {
      let tableList, title, tableType;
      let chartObj = getChartObj(data); //  配置chartObj
      // 算法实现
      let e = 1;
      let calcData = [];
      try {
        if (geneSetting.mode !== mode[2]) {//Relative Standard Curve
          //非RQ时有生物群组
          tableType = 1;
          e = 1;
          tableList = TECHNICAL_REPLICATES_LIST;
          if (endogenousControlTarget.filter(item => item.opt).length > 1) { //  多内参
            if (geneSetting.activeIndex === 2) {
              return;
            }
            calcData = getMultipleCalc(targetCqData, e);
          } else {  //  单内参
            let index = tableList.findIndex(item => item.name === 'Sample' || item.name === '样本' || item.name === 'Biological' || item.name === '生物群组');
            if (geneSetting.activeIndex === 2) {
              tableList[index] = {
                name: "Biological",
                selected: true
              };
              calcData = getSingleCalc(targetCqData, e).calcGroupData;
            } else {
              tableList[index] = {
                name: "Sample",
                selected: true
              };
              calcData = getSingleCalc(targetCqData, e).calcData;
            }
          }
        } else { //  Relative Standard Curve
          if (geneSetting.activeIndex === 2) {
            return;
          }
          tableType = 2;
          calcData = getRelativeCalc(targetCqData, e);
          tableList = RELATIVE_LIST;
        }
        //  设置表格信息
        title = tableList.filter(item => item.selected);
        setTechnicalReplicatesTitle(title);
        dispatch(saveGeneExpressionTableList(tableList));
        if (geneSetting.graphType === "Log10") {
          calcData.forEach(item => typeof item.rq === "number" ? item.rq = Math.log10(item.rq) : null);
        }
        if (!calcData) {
          return;
        }
        let tableData = getTableData(calcData, tableType);
        let allData, option;
        if (geneSetting.activeIndex === 2) {
          let getChartGroup = getChartObjGroup(data);
          allData = getAllGroupData(getChartGroup, calcData, experimentSetting);
          option = getChartGroupOption(allData);
        } else {
          allData = getAllData(chartObj, calcData, experimentSetting);
          option = getChartOption(allData);
        }
        dispatch(saveChartOption(option));
        dispatch(saveTableData(tableData));
        if (geneSetting.mode !== mode[2]) {
          dispatch(saveTechnicalTableData(tableData));
        }
      } catch (e) {
        console.log(e);
      }
    }, [data, endogenousControlTarget, referenceSample, experimentSetting, geneExpressionTableList, geneSetting /*biologicalCqData*//*, , */]);

    //  showInTable菜单操作
    function chooseTableSelect(indey) {
      cloneTechnicalReplicatesList = deepClone(geneExpressionTableList, cloneTechnicalReplicatesList);
      cloneTechnicalReplicatesList[indey].selected = !cloneTechnicalReplicatesList[indey].selected;
      setTechnicalReplicatesTitle(cloneTechnicalReplicatesList.filter(item => item.selected));
      dispatch(saveGeneExpressionTableList(cloneTechnicalReplicatesList));
    }

    //  改变control的状态
    function changeControl(indey) {
      cloneExperimentSetting = deepClone(experimentSetting, cloneExperimentSetting);
      cloneExperimentSetting.targets[indey].control = !cloneExperimentSetting.targets[indey].control;
      cloneExperimentSetting.targets.forEach(item => item.showChart = !item.control); //  如果为内参基因,则不显示柱状图
      dispatch(saveExperimentSetting(cloneExperimentSetting));
      // 与plate界面的EndogenousControlTarget联动
      cloneEndogenousControlTarget = deepClone(endogenousControlTarget, cloneEndogenousControlTarget);
      cloneEndogenousControlTarget[indey].opt = !cloneEndogenousControlTarget[indey].opt;
      dispatch(saveEndogenousControlTarget(cloneEndogenousControlTarget));
    }

    //  改变changeReference的状态
    function changeReference(value, indey) {
      cloneExperimentSetting = deepClone(experimentSetting, cloneExperimentSetting);
      if (cloneExperimentSetting.samples[indey].reference) {
        cloneExperimentSetting.samples[indey].reference = false;  //  已经选中了则取消并同步plate界面为空
        dispatch(saveReferenceSample(""));
      } else {
        cloneExperimentSetting.samples.forEach(item => item.reference = item.name === value);
        // 与plate界面的Reference联动
        dispatch(saveReferenceSample(value));
      }
      dispatch(saveExperimentSetting(cloneExperimentSetting));
    }

    //  改变group changeReference的状态
    function changeGroupReference(value, indey) {
      cloneExperimentSetting = deepClone(experimentSetting, cloneExperimentSetting);
      if (cloneExperimentSetting.groups[indey].reference) {
        cloneExperimentSetting.groups[indey].reference = false;  //  已经选中了则取消并同步plate界面为空
        // dispatch(saveReferenceSample(""));
      } else {
        cloneExperimentSetting.groups?.forEach(item => item.reference = item.name === value);
        // 与plate界面的Reference联动
        // dispatch(saveReferenceSample(value));
      }
      dispatch(saveGeneSetting({
        ...geneSetting,
        biologicalReplicatesGroupReference: value
      }));
      dispatch(saveExperimentSetting(cloneExperimentSetting));
    }

    function changeOmit(indey) {
      cloneTableData = deepClone(tableData, cloneTableData);
      cloneChartOption = deepClone(chartOption, cloneChartOption);
      if (cloneTableData[indey].omit.value) {
        cloneExperimentSetting = deepClone(experimentSetting, cloneExperimentSetting);
        dispatch(saveExperimentSetting({...cloneExperimentSetting}));
      } else {
        let sampleName = cloneTableData[indey]['biological'].value;
        let targetName = cloneTableData[indey]['target'].value;
        console.log(geneSetting);
        if (geneSetting.plotType === 'RQ vs Target') {
          let temp = sampleName;
          sampleName = targetName;
          targetName = temp;
        }
        // console.log(sampleName);
        // console.log(targetName);
        let xAxis = cloneChartOption.xAxis.data.findIndex(item => item === sampleName);
        console.log(cloneTableData);
        let seriesIndex = cloneChartOption.series.findIndex(item => item.name === targetName);
        cloneChartOption.series[seriesIndex].data[xAxis] = 0;
        cloneChartOption.series[seriesIndex + cloneChartOption.series.length / 2].data.splice(xAxis, 1);
        // errorCustom.splice(xAxis , 1);
        // newData.splice(xAxis * 2, 1);
        console.log(cloneChartOption);
        dispatch(saveChartOption(cloneChartOption));
      }

      cloneTableData[indey].omit.value = !cloneTableData[indey].omit.value;
      dispatch(saveTableData(cloneTableData));

      /*
       *    cloneExperimentSetting = deepClone(experimentSetting, cloneExperimentSetting);
       if (cloneExperimentSetting.groups[indey].reference) {
       cloneExperimentSetting.groups[indey].reference = false;  //  已经选中了则取消并同步plate界面为空
       // dispatch(saveReferenceSample(""));
       } else {
       cloneExperimentSetting.groups.forEach(item => item.reference = item.name === value);
       // 与plate界面的Reference联动
       // dispatch(saveReferenceSample(value));
       }
       dispatch(saveGeneSetting({
       ...geneSetting,
       biologicalReplicatesGroupReference: value
       }));
       dispatch(saveExperimentSetting(cloneExperimentSetting));*/
    }

    //  切换面板
    function changePane(activeKey) {
      if (Number(activeKey) === 2) {
        dispatch(saveGeneSetting({...geneSetting, activeIndex: Number(activeKey), plotType: "RQ vs BioGroup"}));
        setPlotType(["RQ vs BioGroup", "RQ vs Target"]);
        setModel(["Normalized Expression (ΔΔCq)", "Normalized Expression (Multiple Controls)"]);
      } else {
        dispatch(saveGeneSetting({...geneSetting, activeIndex: Number(activeKey), plotType: "RQ vs Sample"}));
        setPlotType(["RQ vs Sample", "RQ vs Target"]);
        setModel(["Normalized Expression (ΔΔCq)", "Normalized Expression (Multiple Controls)", "Relative Standard Curve"]);
      }
    }

    function onChange(checked) {
      console.log(`switch to ${checked}`);
      cloneChartOption = deepClone(chartOption, cloneChartOption);
      let orientation = geneSetting.orientation
      if(cloneChartOption.yAxis.hasOwnProperty('splitLine') && orientation==='Vertical Bars'){
        cloneChartOption.yAxis.splitLine.show = !cloneChartOption.yAxis.splitLine.show
      }else {
        cloneChartOption.yAxis['splitLine']={show:false}
      }
      if(cloneChartOption.xAxis.hasOwnProperty('splitLine')&& orientation==='Horizontal Bars'){
        cloneChartOption.xAxis.splitLine.show = !cloneChartOption.xAxis.splitLine.show
      }else {
        cloneChartOption.xAxis['splitLine']={show:false}
      }
      dispatch(saveChartOption(cloneChartOption));
    }

    return (
      <div>
        <section className="mainSection" style={{margin: 0, width: "100%"}}>
          <div className="geneLeft">
            <section className="geneLeftTop">
              <div>{isCN ? "基因表达图谱" : "Bar Chart"}</div>
              <div>
                <div>
                  <GeneChart option={chartOption}/>
                </div>
                {
                  geneSetting.activeIndex === 1
                    ? geneSetting.plotType === "RQ vs Sample"
                    ? <div>
                      <div>{isCN ? "基因" : "Targets"}</div>
                      <ul className="scrollBarStyle">
                        {
                          data.plateSetting.targets.map(item => (
                            <li key={item.uuid}>
                              <div style={{backgroundColor: item.color}}/>
                              <div>{item.name}</div>
                            </li>
                          ))
                        }
                      </ul>
                    </div>
                    : <div>
                      <div>{isCN ? "样品" : "Samples"}</div>
                      <ul className="scrollBarStyle">
                        {
                          data.plateSetting.samples.map(item => (
                            item.type === WELL_TYPE.UNK
                              ? <li key={item.uuid}>
                                <div style={{backgroundColor: item.color}}/>
                                <div>{item.name}</div>
                              </li>
                              : null
                          ))
                        }
                      </ul>
                    </div>
                    :  /*生物*/
                    geneSetting.plotType === "RQ vs BioGroup"
                      ? <div>
                        <div>{isCN ? "基因" : "Targets"}</div>
                        <ul className="scrollBarStyle">
                          {
                            data.plateSetting.targets.map(item => (
                              <li key={item.uuid}>
                                <div style={{backgroundColor: item.color}}/>
                                <div>{item.name}</div>
                              </li>
                            ))
                          }
                        </ul>
                      </div>
                      : <div>
                        <div>{isCN ? "生物群组" : "BioGroup"}</div>
                        <ul className="scrollBarStyle">
                          {
                            experimentSetting.groups.map(item => (
                              item.type === WELL_TYPE.UNK
                                ? <li key={item.name}>
                                  <div style={{backgroundColor: item.color}}/>
                                  <div>{item.name}</div>
                                </li>
                                : null
                            ))
                          }
                        </ul>
                      </div>
                }
              </div>
            </section>
            <section className="geneLeftBottom">
              <Tabs type="card" size="large" onChange={activeKey => changePane(activeKey)} activeKey={geneSetting.activeIndex + ''}>
                <TabPane tab={isCN ? "技术重复" : "View Technical Replicates"} key="1">
                  <section style={{overflow: "auto"}} className="tableStyle scrollBarStyle technicalTable">
                    <ul style={{zIndex: 10}}>
                      {
                        technicalReplicatesTitle.map(item => (
                          <li key={isCN ? translateGene(item.name) : item.name} style={item.width ? {width: item.width} : null}>{isCN ? translateGene(item.name) : item.name}</li>
                        ))
                      }
                    </ul>
                    {/* TODO: 表格信息*/}
                    {
                      tableData.map((item, index) => (
                        <ul key={index}>
                          {item.tag.show ? <li>{item.tag.value}</li> : null}
                          {item.omit.show
                            ? <li>
                              <input type="checkbox" checked={item.omit.value}
                                     onChange={() => changeOmit(index)}
                              />
                            </li>
                            : null}
                          {item.biological.show ? <li>{!item.omit.value ? item.biological.value : "-"}</li> : null}
                          {item.target.show ? <li>{!item.omit.value ? item.target.value : "-"}</li> : null}
                          {item.cqMean.show ?
                            <li>{isNaN(item.cqMean.value) || item.omit.value ? "-" : Number(item.cqMean.value).toFixed(3)}</li> : null}
                          {item._cqMean.show ?
                            <li>{isNaN(item._cqMean.value) || item.omit.value ? "-" : Number(item._cqMean.value).toFixed(3)}</li> : null}
                          {item._cqSd.show ?
                            <li>{isNaN(item._cqSd.value) || item.omit.value ? "-" : Number(item._cqSd.value).toFixed(3)}</li> : null}
                          {(item.__cq && item.__cq.show) ?
                            <li>{isNaN(item.__cq.value) || item.omit.value ? "-" : Number(item.__cq.value).toFixed(3)}</li> : null}
                          {item.rq.show ?
                            <li>{isNaN(item.rq.value) || item.omit.value ? "-" : Number(item.rq.value).toFixed(3)}</li> : null}
                          {item.rqMin.show ?
                            <li>{isNaN(item.rqMin.value) || item.omit.value ? "-" : Number(item.rqMin.value).toFixed(3)}</li> : null}
                          {item.rqMax.show ?
                            <li>{isNaN(item.rqMax.value) || item.omit.value ? "-" : Number(item.rqMax.value).toFixed(3)}</li> : null}
                        </ul>
                      ))
                    }
                  </section>
                </TabPane>
                {
                  (geneSetting.mode === mode[2])
                    ? null
                    : <TabPane tab={isCN ? "生物重复" : "View Biological Groups"} key="2">
                      <section style={{overflow: "auto"}} className="tableStyle scrollBarStyle technicalTable">
                        <ul style={{zIndex: 10}}>
                          {
                            technicalReplicatesTitle.map(item => (
                              <li key={isCN ? translateGene(item.name) : item.name}>{isCN ? translateGene(item.name) : item.name}</li>
                            ))
                          }
                        </ul>
                        {/*TODO: 表格信息*/}
                        {
                          tableData.map((item, index) => (
                            <ul key={index}>
                              {item.tag.show ? <li>{item.tag.value}</li> : null}
                              {item.omit.show
                                ? <li>
                                  <input type="checkbox" checked={item.omit.value}
                                         onChange={() => changeOmit(index)}
                                  />
                                </li>
                                : null}
                              {item.biological.show ? <li>{!item.omit.value ? item.biological.value : "-"}</li> : null}
                              {item.target.show ? <li>{!item.omit.value ? item.target.value : "-"}</li> : null}
                              {item.cqMean.show ?
                                <li>{isNaN(item.cqMean.value) || item.omit.value ? "-" : Number(item.cqMean.value).toFixed(3)}</li> : null}
                              {item._cqMean.show ?
                                <li>{isNaN(item._cqMean.value) || item.omit.value ? "-" : Number(item._cqMean.value).toFixed(3)}</li> : null}
                              {item._cqSd.show ?
                                <li>{isNaN(item._cqSd.value) || item.omit.value ? "-" : Number(item._cqSd.value).toFixed(3)}</li> : null}
                              {(item.__cq && item.__cq.show) ?
                                <li>{isNaN(item.__cq.value) || item.omit.value ? "-" : Number(item.__cq.value).toFixed(3)}</li> : null}
                              {item.rq.show ?
                                <li>{isNaN(item.rq.value) || item.omit.value ? "-" : Number(item.rq.value).toFixed(3)}</li> : null}
                              {item.rqMin.show ?
                                <li>{isNaN(item.rqMin.value) || item.omit.value ? "-" : Number(item.rqMin.value).toFixed(3)}</li> : null}
                              {item.rqMax.show ?
                                <li>{isNaN(item.rqMax.value) || item.omit.value ? "-" : Number(item.rqMax.value).toFixed(3)}</li> : null}
                            </ul>
                          ))
                        }
                      </section>
                    </TabPane>
                }
              </Tabs>
              {/*<div onClick={() => setShowInTable(!showInTable)}>Show in table</div>*/}
              {
                showInTable
                  ? <div className="showInTable">
                    <ul className="scrollBarStyle">
                      {
                        geneExpressionTableList.map((item, index) => (
                          <li key={item.name}>
                            <div className={item.selected ? "selectedStyle" : ""}
                                 onClick={() => chooseTableSelect(index)}
                            />
                            <div>{item.name}</div>
                          </li>
                        ))
                      }
                    </ul>
                  </div>
                  : null
              }
            </section>
          </div>
          <div className="geneRight">
            <div>
              <Title name={isCN ? "基因表达设置" : "Gene Expression Setting"}/>
              <ul className="geneRightTop">
                <li>
                  <div>{isCN ? "分析模式" : "Mode"}</div>
                  <Dropdown
                    overlay={
                      <Menu>
                        {
                          mode.map(item => (
                            <Menu.Item key={item}>
                              <div style={{...MENU_STYLE, width: "300px", marginBottom: 5}}
                                   onClick={() => dispatch(saveGeneSetting({...geneSetting, mode: item}))}
                              >{isCN ? translateGene(item) : item}</div>
                            </Menu.Item>
                          ))
                        }
                      </Menu>
                    }
                    overlayClassName="antdDropDownStyle"
                    placement="bottomCenter"
                    trigger={['click']}
                  >
                    <div>
                      <div>{isCN ? translateGene(geneSetting.mode) : geneSetting.mode}</div>
                      <span/>
                    </div>
                  </Dropdown>
                </li>
                <li>
                  <div>{isCN ? "绘图类型" : "Plot Type"}</div>
                  <Dropdown
                    overlay={
                      <Menu>
                        {
                          plotType.map(item => (
                            <Menu.Item key={item}>
                              <div style={{...MENU_STYLE, width: "300px", marginBottom: 5}}
                                   onClick={() => dispatch(saveGeneSetting({...geneSetting, plotType: item}))}
                              >{isCN ? translateGene(item) : item}</div>
                            </Menu.Item>
                          ))
                        }
                      </Menu>
                    }
                    overlayClassName="antdDropDownStyle"
                    placement="bottomCenter"
                    trigger={['click']}
                  >
                    <div>
                      <div>{isCN ? translateGene(geneSetting.plotType) : geneSetting.plotType}</div>
                      <span/>
                    </div>
                  </Dropdown>
                </li>
                <li>
                  <div>{isCN ? "图谱类型" : "Graph Type"}</div>
                  <Dropdown
                    overlay={
                      <Menu>
                        {
                          graphType.map(item => (
                            <Menu.Item key={item}>
                              <div style={{...MENU_STYLE, width: "300px", marginBottom: 5}}
                                   onClick={() => dispatch(saveGeneSetting({...geneSetting, graphType: item}))}
                              >{isCN ? translateGene(item) : item}</div>
                            </Menu.Item>
                          ))
                        }
                      </Menu>
                    }
                    overlayClassName="antdDropDownStyle"
                    placement="bottomCenter"
                    trigger={['click']}
                  >
                    <div>
                      <div>{isCN ? translateGene(geneSetting.graphType) : geneSetting.graphType}</div>
                      <span/>
                    </div>
                  </Dropdown>
                </li>
                <li>
                  <div>{isCN ? "方向" : "Orientation"}</div>
                  <Dropdown
                    overlay={
                      <Menu>
                        {
                          orientation.map(item => (
                            <Menu.Item key={item}>
                              <div style={{...MENU_STYLE, width: "300px", marginBottom: 5}}
                                   onClick={() => dispatch(saveGeneSetting({...geneSetting, orientation: item}))}
                              >{isCN ? translateGene(item) : item}</div>
                            </Menu.Item>
                          ))
                        }
                      </Menu>
                    }
                    overlayClassName="antdDropDownStyle"
                    placement="bottomCenter"
                    trigger={['click']}
                  >
                    <div>
                      <div>{isCN ? translateGene(geneSetting.orientation) : geneSetting.orientation}</div>
                      <span/>
                    </div>
                  </Dropdown>
                </li>
                <li>
                  <div style={{width: 325}}>{isCN ? "生物群组对照" : "Biological Replicates Group Reference"}</div>
                  <Dropdown
                    overlay={
                      <Menu>
                        {
                          experimentSetting.groups?.map(item => (
                            <Menu.Item key={item.uuid + item.name}>
                              <div style={{...MENU_STYLE, width: "105px", marginBottom: 5}}
                                   onClick={() => {
                                     let index = experimentSetting.groups.findIndex(it => it.name === item.name);
                                     cloneExperimentSetting = deepClone(experimentSetting, cloneExperimentSetting);
                                     cloneExperimentSetting.groups.forEach(item => item.reference = false);
                                     cloneExperimentSetting.groups[index].reference = true;  //  已经选中了则取消并同步plate界面为空
                                     dispatch(saveExperimentSetting(cloneExperimentSetting));
                                     dispatch(saveGeneSetting({
                                       ...geneSetting,
                                       biologicalReplicatesGroupReference: item.name
                                     }));
                                   }}
                              >{item.name}</div>
                            </Menu.Item>
                          ))
                        }
                      </Menu>
                    }
                    overlayClassName="antdDropDownStyle"
                    placement="bottomCenter"
                    trigger={['click']}
                  >
                    <div style={{width: 105}}>
                      <div style={{width: 65}}>{geneSetting.biologicalReplicatesGroupReference}</div>
                      <span/>
                    </div>
                  </Dropdown>
                </li>
                <li>
                  <div  style={{width: 325}}>{isCN ? "坐标系分隔线" : "Coordinate Separator"}</div>
                  <Switch defaultChecked onChange={onChange} size="default" className='coordinate'/>
                </li>
              </ul>
            </div>
            <div className="geneRightMiddle">
              <div>{isCN ? "实验设置" : "Experiment Setting"}</div>
              <div className="targetsTable">
                <div>{isCN ? "基因" : "Targets"}</div>
                <ul>
                  <li/>
                  <li>{isCN ? "名称" : "Name"}</li>
                  <li>{isCN ? "内参基因" : "Control"}</li>
                  <li>{isCN ? "颜色" : "Color"}</li>
                  <li>{isCN ? "扩增效率" : "Effienciency"}</li>
                  <li>{isCN ? "显示" : "Show Chart"}</li>
                </ul>
                <section className="scrollBarStyle">
                  {
                    experimentSetting.targets.map((item, index) => (
                      <ul key={item.name}>
                        <li>{index + 1}</li>
                        <li>{item.name}</li>
                        <li onClick={() => changeControl(index)}>
                          {item.control ? <div/> : null}
                        </li>
                        <li>
                          <div style={{backgroundColor: `${item.color}`}}/>
                        </li>
                        <li>
                          <input type="number"
                                 defaultValue={item.e < 0 ? 1 : (+item.e).toFixed(3)}
                                 onBlur={e => {
                                   cloneExperimentSetting = deepClone(experimentSetting, cloneExperimentSetting);
                                   cloneExperimentSetting.targets[index].e = Number(e.target.value);
                                   dispatch(saveExperimentSetting(cloneExperimentSetting));
                                 }}
                          />
                        </li>
                        <li>
                          <input type="checkbox" checked={item.showChart}
                                 onChange={() => {
                                   cloneExperimentSetting = deepClone(experimentSetting, cloneExperimentSetting);
                                   cloneExperimentSetting.targets[index].showChart = !cloneExperimentSetting.targets[index].showChart;
                                   dispatch(saveExperimentSetting(cloneExperimentSetting));
                                 }}
                          />
                        </li>
                      </ul>
                    ))
                  }
                </section>
              </div>
              {
                geneSetting.activeIndex !== 2
                  ? <div className="samplesTable">
                    <div>{isCN ? "样品" : "Samples"}</div>
                    <ul>
                      <li/>
                      <li>{isCN ? "名称" : "Name"}</li>
                      <li>{isCN ? "对照样品" : "Reference"}</li>
                      <li>{isCN ? "颜色" : "Color"}</li>
                      <li>{isCN ? "显示" : "Show Chart"}</li>
                    </ul>
                    <section className="scrollBarStyle">
                      {
                        experimentSetting.samples.map((item, index) => (
                          item.type === WELL_TYPE.UNK
                            ? <ul key={item.name}>
                              <li>{index + 1}</li>
                              <li>{item.name}</li>
                              <li onClick={() => changeReference(item.name, index)}>
                                {item.reference ? <div/> : null}
                              </li>
                              <li>
                                <div style={{backgroundColor: `${item.color}`}}/>
                              </li>
                              <li>
                                <input type="checkbox" checked={item.showChart}
                                       onChange={() => {
                                         cloneExperimentSetting = deepClone(experimentSetting, cloneExperimentSetting);
                                         cloneExperimentSetting.samples[index].showChart = !cloneExperimentSetting.samples[index].showChart;
                                         dispatch(saveExperimentSetting(cloneExperimentSetting));
                                       }}
                                />
                              </li>
                            </ul>
                            : null
                        ))
                      }
                    </section>
                  </div>
                  : <div className="samplesTable">
                    <div>{isCN ? "生物群组" : "Biological Group"}</div>
                    <ul>
                      <li/>
                      <li>{isCN ? "名称" : "Name"}</li>
                      <li>{isCN ? "对照样品" : "Reference"}</li>
                      <li>{isCN ? "颜色" : "Color"}</li>
                      <li>{isCN ? "显示" : "Show Chart"}</li>
                    </ul>
                    <section className="scrollBarStyle">
                      {
                        experimentSetting.groups?.map((item, index) => (
                          <ul key={item.name}>
                            <li>{index + 1}</li>
                            <li>{item.name}</li>
                            <li onClick={() => changeGroupReference(item.name, index)}>
                              {item.reference ? <div/> : null}
                            </li>
                            <li>
                              <div style={{backgroundColor: `${item.color}`}}/>
                            </li>
                            <li>
                              <input type="checkbox" checked={item.showChart}
                                     onChange={() => {
                                       cloneExperimentSetting = deepClone(experimentSetting, cloneExperimentSetting);
                                       cloneExperimentSetting.groups[index].showChart = !cloneExperimentSetting.groups[index].showChart;
                                       dispatch(saveExperimentSetting(cloneExperimentSetting));
                                     }}
                              />
                            </li>
                          </ul>
                        ))
                      }
                    </section>
                  </div>
              }

            </div>
          </div>
        </section>
      </div>
    );
  }
)
;
